msg_tool\scripts\emote/
rle.rs1use crate::ext::io::*;
3use anyhow::Result;
4use std::io::{Read, Seek, SeekFrom};
5
6const LZSS_LOOKAHED: usize = 1 << 7;
7
8pub fn rl_decompress<T: Read + Seek>(
12 mut input: T,
13 align: usize,
14 actual_size: Option<usize>,
15) -> Result<Vec<u8>> {
16 let mut output = if let Some(size) = actual_size {
17 Vec::with_capacity(size)
18 } else {
19 Vec::new()
20 };
21 let mut readed = input.stream_position()?;
22 let len = input.stream_length()?;
23 while readed < len {
24 let current = input.read_u8()? as usize;
25 readed += 1;
26 let count;
27 if (current & LZSS_LOOKAHED) != 0 {
28 count = (current ^ LZSS_LOOKAHED) + 3;
29 let buf = input.read_exact_vec(align)?;
30 readed += align as u64;
31 for _ in 0..count {
32 output.extend_from_slice(&buf);
33 }
34 } else {
35 count = (current + 1) * align;
36 let buf = input.read_exact_vec(count)?;
37 readed += count as u64;
38 output.extend_from_slice(&buf);
39 }
40 }
41 Ok(output)
42}
43
44fn compress_bound<T: Read + Seek>(input: &mut T, align: usize) -> Result<(usize, u8, Vec<u8>)> {
45 let pos = input.stream_position()?;
46 let mut curpos = pos;
47 let len = input.stream_length()?;
48 let mut buffer = vec![0u8; align];
49 let mut tmp = vec![0u8; align];
50 input.read_exact(&mut buffer)?;
51 curpos += align as u64;
52 let mut count = 1usize;
53 for _ in 1..LZSS_LOOKAHED + 2 {
54 if curpos >= len {
55 break;
56 }
57 input.read_exact(&mut tmp)?;
58 curpos += align as u64;
59 if buffer == tmp {
60 count += 1;
61 } else {
62 break;
63 }
64 }
65 input.seek(SeekFrom::Start(pos))?;
66 if count >= 3 {
67 return Ok((count, (count - 3) as u8 | LZSS_LOOKAHED as u8, buffer));
68 }
69 Ok((0, 0, buffer))
70}
71
72fn compress_bound_np<T: Read + Seek>(input: &mut T, align: usize) -> Result<(usize, u8)> {
73 let pos = input.stream_position()?;
74 let mut curpos = pos;
75 let len = input.stream_length()?;
76 input.seek_relative(align as i64)?;
77 curpos += align as u64;
78 let mut count = 1;
79 for _ in 1..LZSS_LOOKAHED {
80 if curpos >= len {
81 break;
82 }
83 let (ncount, _cmd, _buf) = compress_bound(input, align)?;
84 if ncount == 0 {
85 input.seek_relative(align as i64)?;
86 count += 1;
87 curpos += align as u64;
88 } else {
89 break;
90 }
91 }
92 input.seek(SeekFrom::Start(pos))?;
93 Ok((count, (count - 1) as u8))
94}
95
96pub fn rl_compress<T: Read + Seek>(mut input: T, align: usize) -> Result<Vec<u8>> {
99 let mut output = Vec::new();
100 let len = input.stream_length()?;
101 let mut readed = input.stream_position()?;
102 while readed < len {
103 let (count, cmd, buf) = compress_bound(&mut input, align)?;
104 if count > 0 {
105 output.push(cmd);
106 output.extend_from_slice(&buf);
107 readed += (count * align) as u64;
108 input.seek_relative((count * align) as i64)?;
109 } else {
110 let (ncount, ncmd) = compress_bound_np(&mut input, align)?;
111 output.push(ncmd);
112 let buf = input.read_exact_vec(ncount * align)?;
113 output.extend_from_slice(&buf);
114 readed += (ncount * align) as u64;
115 }
116 }
117 Ok(output)
118}